package com.eco.netty;

import com.eco.utils.KndUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author xulinyu
 */
@Slf4j
@Data
public class GenericNettyClient {

    private String clientId;

    private String host;

    private int port;

    private final NioEventLoopGroup group = new NioEventLoopGroup();

    private Bootstrap bootstrap;

    /**
     * 开灯指令
     */
    private String onCommand;

    /**
     * 关灯指令
     */
    private  String offCommand;


    public GenericNettyClient(String clientId, String host, int port,  String onCommand, String offCommand) {
        this.clientId = clientId;
        this.host = host;
        this.port = port;
        this.onCommand = onCommand;
        this.offCommand = offCommand;
    }

    public void connect() {
        bootstrap = new Bootstrap();
        this.bootstrap.group(this.group)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new ChannelInitializer<SocketChannel>(){
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast(new KndEncoder());
                        pipeline.addLast(new KndDecoder());
                        pipeline.addLast(new IdleStateHandler(0L, 1L, 0L, TimeUnit.HOURS));
                        pipeline.addLast(new SensorHexHandler(GenericNettyClient.this,host,port,clientId,onCommand));
                    }
                });

        // 连接到服务器
        ChannelFuture future = bootstrap.connect(host, port);
        future.addListener((ChannelFutureListener) futureListener -> {
            if (futureListener.isSuccess()) {
                log.info("连接Netty服务端{}:{}成功!!", host, port);
            } else {
                log.warn("连接Netty服务端{}:{}失败，准备30s后进行断线重连!!",host, port);
                futureListener.channel().eventLoop().schedule(this::connect, 30, TimeUnit.SECONDS);
            }
        });

    }


    public void scheduleReconnect() {
        group.schedule(this::connect, 30, TimeUnit.SECONDS);
        log.info("Reconnecting in 30 seconds...");
    }


    public void shutdown() {
        this.group.shutdownGracefully();
        log.info("sensor shutdown");
    }


    /**
     * 灯光的开关控制功能
     */
    public void turnOn(){
        KndUtil.sendCommand(clientId,onCommand);
    }

    public void turnOff(){
        KndUtil.sendCommand(clientId,offCommand);
    }
}
